約 5,161,061 件
https://w.atwiki.jp/widget/pages/9.html
https://w.atwiki.jp/teremi2/pages/16.html
こうすると見出しを作れるよ 説明しよう 最初以外はこれ使うといいよ、見やすいし 表を作るのは こんな感じ 大きさ=25 大きさ=35 アイコン 絵文字 こんな感じ で 画像を表に 混ぜることも できるよ。表内で改行もできる デカくて赤い文字 ←重要! 普通の18pxの文字 引用文だよ。by テレみ トップページ 違うサイトへのリンク 点を打つだけで 改行がでかくなって 箇条書きが見やすくなるぜ 普通に書くと、 結構行間狭くて 見づらい よく使う あ い う え お あああ あああ videoプラグインエラー 正しいURLを入力してください。 videoプラグインエラー 正しいURLを入力してください。
https://w.atwiki.jp/htmlsakusei/pages/3.html
カウンター 今日 - 人 昨日 - 人 合計 - 人 現在-人が閲覧中。 更新履歴 取得中です。
https://w.atwiki.jp/kyoto-tutorial/pages/9.html
@wikiにはいくつかの便利なプラグインがあります。 アーカイブ コメント ニュース 動画(Youtube) 編集履歴 関連ブログ これ以外のプラグインについては@wikiガイドをご覧ください = http //atwiki.jp/guide/
https://w.atwiki.jp/akasatanahama/pages/135.html
概要 MinecraftForgeのイベント機能を利用して既存の処理に追加動作を施す。 2017/6/14 全体を確認し、修正や変更を行いました。 仕組み 今までMinecraft内のソースを見てみて、「ForgeHooks」や「EVENT_BUS」という記述を見たことはあるだろうか。 例えば、EntityLivingBase/onUpdateのメソッドを見てみよう。 public void onUpdate() { if (ForgeHooks.onLivingUpdate(this)) return; super.onUpdate(); /* 略 */ } /* 略 */ このように、Forgeがシステムを書き換えてイベントを起こしている場所がある。 ここで、@SubscribeEventのアノテーションを付け、適切な処理をしてあるメソッドが呼ばれる。 クラス書き換えと違って使えるものは限られるものの、競合が起きにくくかつ実装しやすい手段である。 ソースコード AluminiumMod.java package tutorial.aluminiummod; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.eventhandler.SubscribeEvent; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntityIronGolem; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.util.DamageSource; import net.minecraft.world.ChunkPosition; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.event.entity.living.LivingEvent; import net.minecraftforge.event.entity.living.LivingHurtEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.ExplosionEvent; import java.util.Iterator; @Mod(modid = "AluminiumMod", name = "Aluminium Mod", version = "1.0.0") public class AluminiumMod { @EventHandler public void preInit(FMLPreInitializationEvent event) { // Event処理を記述しているクラスをForgeに登録する。 // Forgeのイベントを受け取る。 MinecraftForge.EVENT_BUS.register(this); // FMLのイベントを受け取りたい場合は以下のように追加で登録する。 //FMLCommonHandler.instance().bus().register(this); } /** EntityLivingBaseがダメージを負った時のイベント。 */ @SubscribeEvent public void onLivingHurt(LivingHurtEvent event) { // プレイヤーがアイアンゴーレムに対して攻撃した時、プレイヤーに同量のダメージを与える。 Entity sourceEntity = event.source.getEntity(); if (event.entityLiving instanceof EntityIronGolem sourceEntity != null sourceEntity instanceof EntityPlayer) sourceEntity.attackEntityFrom(DamageSource.causeMobDamage(event.entityLiving), event.ammount); } /** プレイヤーがEntityを攻撃した時のイベント。 */ @SubscribeEvent public void onPlayerAttackEntity(AttackEntityEvent event) { // ダイヤモンドを持っていたら、HPをハート10個分回復する。 if (event.entityPlayer.getHeldItem() != null event.entityPlayer.getHeldItem().getItem() == Items.diamond) event.entityPlayer.heal(20); } /** EntityLivingBaseが更新される時のイベント。 */ @SubscribeEvent public void onLivingUpdate(LivingEvent.LivingUpdateEvent event) { // クリーパーなら雷雨時に巨匠化させる。 if (event.entityLiving instanceof EntityCreeper event.entityLiving.worldObj.isThundering()) event.entityLiving.getDataWatcher().updateObject(17, (byte) 1); } /** 爆発が起こった時のイベント。 */ @SubscribeEvent public void onExplosionDetonate(ExplosionEvent.Detonate event) { System.out.println("onExplosionDetonate"); // クリーパーが起こした爆発なら、EntityMob継承のEntityを全て爆発対象から除外する。(ダメージやノックバックがなくなる。) if (event.explosion.exploder != null event.explosion.exploder instanceof EntityCreeper) { Iterator Entity iterator = event.getAffectedEntities().iterator(); while (iterator.hasNext()) { if (iterator.next() instanceof EntityMob) iterator.remove(); } } // ブロック破壊と炎上があるなら、氷と氷塊を破壊対象から除外する。 if (event.explosion.isSmoking event.explosion.isFlaming) { Iterator ChunkPosition iterator = event.getAffectedBlocks().iterator(); while (iterator.hasNext()) { ChunkPosition position = iterator.next(); Block block = event.world.getBlock(position.chunkPosX, position.chunkPosY, position.chunkPosZ); if (block == Blocks.ice || block == Blocks.packed_ice) iterator.remove(); } } } /** プレイヤーがブロックを設置した時のイベント。 */ @SubscribeEvent public void onPlayerBlockPlace(BlockEvent.PlaceEvent event) { // 土にカーソルを合わせてダイヤモンドブロックを置こうとしたらキャンセルする。 if (event.placedBlock == Blocks.diamond_block event.placedAgainst == Blocks.dirt) event.setCanceled(true); } } 解説 EventBus イベントを管理するためのクラス。 ForgeとFMLが別でインスタンスを持っているため、利用したいイベントのパッケージを確認して対応したものに登録する。 このチュートリアルではForgeのものしか使っていないが、FMLにもTickEventやKeyInputEventなど多くのイベントが用意されている。 void register(Object target) イベントを処理するメソッドがあるクラスのインスタンスを渡す。 このクラス内にある、@SubscribeEventがついており引数がEventを継承するクラス一つのみのメソッドが、イベントリスナーとして登録される。 Event Minecraft内にフックされているイベントの元クラス。 これを継承したクラスがインスタンス化され、イベントが発生する。 親子関係があるイベントでは、親クラスを引数とするメソッドは、その全ての子クラスのイベントを受け取る。 例:ExplosionEventを引数とするメソッドはExplosionEvent.StartとExplosionEvent.Detonateの双方のイベントを受け取る。(一度の爆発につき二回呼ばれる。) void setResult(Result value) Eventに@HasResultがついている場合、これを利用するとフック元の残りの動作をキャンセルしたり別のものにしたりできる。 setCanseled(boolean cansel) Eventに@Canselableがついている場合、ここにtrueを入れるとフック元の残りの動作をなくせる。 LivingHurtEvent EntityLivingBaseを継承したEntityがダメージを負った時のイベント。 DamageSource source ダメージの種類や性質を持つクラス。 float ammount ダメージ量 EntityLivingBase entityLiving 親クラスであるLivingEventで定義。 LivingHurtEventの場合はダメージを受けたEntity。 AttackEntityEvent プレイヤーがEntityを攻撃した時のイベント。 Entity target 攻撃対象のEntity。 EntityPlayer entityPlayer 親クラスであるPlayerEventで定義。 攻撃したプレイヤー。 LivingUpdateEvent EntityLivingBaseを継承したEntityが更新される時のイベント。 EntityLivingBase.onUpdate()の最初で発生している。 EntityLivingBase entityLiving 親クラスであるLivingEventで定義。 LivingUpdateEventの場合は更新されるEntity。 Detonate ExplosionEventの子クラス。 爆発が起こった時のイベント。 ExplosionEventの別の子クラスであるStartは爆発処理の開始時だが、こちらは影響対象のリストアップとその処理の間で発生する。 そのため、影響対象の操作が可能となる。 List ChunkPosition getAffectedBlocks() 爆発の影響を受けるブロックのリストを返す。 Explosionのインスタンスから直接取得しても同じ。 List Entity getAffectedEntities() 爆発の影響を受けるEntityのリストを返す。 操作すると、爆発処理(ダメージや移動)に反映される。 Explosionはインスタンス変数として持っていないが、DetonateがentityListとして保持している。 World world 親クラスであるExplosionEventで定義。 爆発の発生したWorldのインスタンス。 Explosion explosion 親クラスであるExplosionEventで定義。 爆発の処理を行うクラス。 性質などをインスタンス変数として持っている。 boolean isSmoking 煙パーティクルを発生させるか。 ブロックの破壊もこれで管理されている。 boolean isFlaming 炎を発生させるか。 PlaceEvent プレイヤーがブロックを設置した時のイベント。 実際の設置処理は一通り終わっているので、座標とWorldからは設置されたブロックを得られる。 EntityPlayer player ブロックを設置したプレイヤー。 ItemStack itemInHand プレイヤーが手に持っているItemStackのインスタンス。 ブロック設置の処理を行う前の状態になっている。 BlockSnapshot blockSnapshot ブロック置き換え処理の途中で、置き換え前のブロックを一時的に保持するために使われている。 置き換えられたブロック(通常は空気)を得たい場合はこれを利用する。 また、座標やディメンションIDなども得られる。 Block placedBlock 設置されたブロック。 Block placedAgainst 設置の際に視線の先にあった(設置の支えとなった)ブロック。 コメント この項目に関する質問などをどうぞ。 メニューの「イベントの追加」のリンクがおかしいです。 - mod初心者 2017-05-20 21 26 17 ご指摘ありがとうございます。見事に製作の「製」の字を「制」にしておりました。修正しましたのでご確認ください。 - Tom Kate 2017-05-20 21 45 11 BlockPlacedEventですが、「== Blocks.air」ではなく「!= Blocks.air」だと思います。 - mod初心者 2017-05-30 17 23 56 「設置前のブロックが」空気ブロックであることを判定してますので問題ありません。 - Tom Kate 2017-05-30 19 23 53 ではこのイベントは何をするイベントなんですか? - mod初心者 2017-06-02 18 26 18 返信が遅くなってしまい申し訳ありません。PlaceEvent.placedAgainstは置き換えられたブロックではなく、ブロック設置直前に視線の先にあったブロックでした。本来、ダイヤモンドブロックを設置した時にキャンセルする、という処理を行いたかったため、正しいご指摘でした。少し処理を変更しましたので、ご確認ください。ご迷惑をおかけしてしまい、申し訳ありませんでした。 - 赤砂蛇凪浜 2017-06-14 19 15 35 こちらも説明不足ですみませんでした。大幅なコード修正ありがとうございました! - mod初心者 2017-06-16 19 03 04 List remover = new ArrayList();の型の設定やremover.addの括弧が多いような気がします。 - 名無しさん 2017-05-30 18 23 33 Entity型へのキャストを行っておりますので問題ありません。EclipseやIDEAなどでエラーが出ないかどうかご確認ください。 - Tom Kate 2017-05-30 19 25 56 remover.addのEntityMobの括弧足りなくてエラーになります。 - 名無しさん 2017-06-01 22 25 35 上のは解決しましたが、ListとArrayListの型は設定しなくて良いのでしょうか? - 名無しさん 2017-06-02 18 10 51 返信が遅くなってしまい申し訳ありません。ジェネリクスを利用しないとビルド時に警告が出ます。該当部分の処理方法を変更しましたが、同様のエラーは出ないよう修正しておきました。 - 赤砂蛇凪浜 2017-06-14 19 16 23 いつもこちらで勉強させていただいています。質問なのですが、下にあるブロックを掘ってアイテム化する(ドリルのように)というのは、どうすればいいのでしょうか。onDestroyByPlayerなどいろいろ試しましたが、壊れるのではなくて消えるようになってしまって困っています。 - 美羽 2017-06-04 09 47 06 返信が遅くなってしまい申し訳ありません。どのMODのドリルを指しているのかわかりませんが、アイテムを手に持ちブロックを右クリックした時の処理は、Itemを継承したクラスonItemUseを利用できます。また、ツルハシなどのように左クリック長押しによるブロック破壊の速度を上げたいのであれば、「ツール類の追加」を参考にしていただけると思います。onDestroyByPlayerという名のメソッドは見当たりませんでしたが、Block.onBlockDestroyedByPlayer(World, int, int, int, int)のことでしたら、ブロックがプレイヤーに破壊された時に呼ばれるメソッドです。ブロック破壊時のアイテムのドロップは、Block.harvestBlock(World, EntityPlayer, int, int, int, int)などを見ると分かるかもしれません。 - 赤砂蛇凪浜 2017-06-14 19 17 42 ありがとうございます。単に、下にあるブロックを破壊してアイテム化するブロックが作りたいのです - 美羽 2017-06-22 14 28 21 すみません、途中で書き込んでしまいました - 美羽 2017-06-22 14 29 02 Setblocktoairのように消えてしまうのではなく、つるはしで掘ったときのように徐々にひびが入って、破砕、アイテム化させたいです。 - 美羽 2017-06-22 14 35 06 返信が遅くなってしまい申し訳ありません。コメントのツリーを編集させていただきました。私も挑戦したことがないため、軽く調べてみましたが、間違っていたらすみません。ブロックのひび割れのレンダリングはRenderGlobalを通して行っているようです。drawBlockDamageTextureメソッドでレンダリングしているようですが、対象となるブロックはプレイヤーのEntityIDをキーとしたマップのdamagedBlocksで保持しており、ブロックやTileEntityからの介入は容易ではないと思います。 - 赤砂蛇凪浜 2017-07-08 18 29 55 名前
https://w.atwiki.jp/arma2dayz/pages/60.html
ArmaⅡLauncherを使ったBeta導入 現在、DayZをプレイできるサーバーの多くが、ArmaⅡOAのベータパッチを導入する必要があります。 ここでは、海外の有志が作成したArmaⅡLauncherを利用したbetaパッチの導入方法を記載いたします ArmaⅡLauncherを利用することで、起動設定などのめんどうな設定を省くことが出来、 簡単にbetaパッチを当てることが可能になります。 なお、これらの作業はArma2及びArma2OAがインストールしてあり、dayzMODファイルがArma2OAのフォルダに既に準備出来ている状態で行ってください ランチャーを利用するメリット 起動設定などの必要性がない 手動インストールと殆ど変わらないので、ダウンデート、ベータパッチの変更が容易 パッケージ版Arma2とSteam版Arma2OAのような違う状態のArma2をCO化して起動することが出来る。 Steamから起動することで、Steamを使ってスクリーンショットが撮れる。(Steamのウィンドウ左下から「ゲームの追加...」→「非Steamゲームを追加...」からArmaⅡLauncherを登録する必要がある。) ランチャーを利用するデメリット ベータパッチ等がアップデートされたら自分でその毎アップデートを行わないといけない 事前に済ませておくこと Arma2のインストール Arma2 OAのインストール @dayzのMOD関連をArma2OAをインストールした場所に設置しておくこと 必要な物 ArmaⅡLauncher Ver1.40 Arma2OA用ベータパッチ ArmaⅡLauncher導入方法 こちらのページ(http //www.armaholic.com/page.php?id=8241)の一番下のDownload from FTPよりArmaⅡLauncher Ver1.40をダウンロードします。 ダウンロードが終了後、落ちてきたzipを解凍し、出来たファイルArma2Launcherver1.4.0.msiを起動し、ランチャー本体をインストールしましょう。 ベータパッチの準備 こちらのArma2ベータパッチ置き場(http //www.arma2.com/beta-patch.php)より、必要なベータパッチのzipをダウンロードしてください。 必要なベータパッチはサーバーの状況によって変わりますが、基本的には最新のベータパッチで問題ありません。 (12年6月19日現在の最新ベータパッチはARMA2_OA_Build_93825.zip) ベータパッチのzipがダウンロード完了しましたら、解凍をして中身のファイルを起動してベータパッチのファイルをインストールしましょう。 ArmaⅡランチャーの設定を行う 上二つのファイルをインストール完了しましたらArma2Launcher.exeを起動しましょう。 起動しましたら、上の部分にあるLaunchOptionタブをクリックしましょう。 左下のArna2 Executable Locationの部分のBrowseを押し、Arma2.exeの場所を指定しましょう。 steam版Arma2の場合、デフォルトではC \Program Files\Steam\steamapps\common\arma 2\arma2.exeにになります。 その下のArma2 Betaの部分は空白でかまいません。 次にその右にあるArna2OA Executable Locationの部分のbrowseを押しArma2OA.exeの場所を指定しましょう。 steam版Arma2OAの場合、デフォルトでは、C \Program Files\Steam\steamapps\common\arma 2 operation arrowhead\Arma2OA.exeになります。 次にその下にあるArma2OA Betaのbrowseをクリックします。 ここでは、先ほどインストールしたベータパッチのexeを指定します。 インストールが正常であれば、ベータパッチのexeファイルはarma 2 operation arrowheadフォルダ内のExpansion\beta\arma2oa.exeにあります。 steam版がデフォルトの場合ではC \Program Files\Steam\steamapps\common\arma 2 operation arrowhead\Expansion\beta\arma2oa.exeになります。 以上の設定が終わりましたら画面右上のOther Optionの項目に移動し、Run Betaにチェックを入れてください。 画面上記にあるAddonsタブをクリックし、上にあるRefleshをクリックしましょう。 Arma2OAのフォルダ内にdayzmodが無事に導入されていれば、Availabe Addonsに@dayzという項目が追加されているはずです。 (@dayzが表示されていない場合は、dayz関連のファイルが準備されていないので、Dayzmodファイルを用意してください。) @dayzをドラッグして右のAddonsGroupにあるAddon/ModsのGroup1に入れてください。 無事に入れれば、Addon/Mods、Group1、@dayz全てにチェックを入れてください。 なお、dayz以外のMODを導入している場合、dayz以外のチェックは必ず外してください。 これが完了しましたら、最後に右下にあるGame VersionをArma2-COを選択してください。 これで、StartGameを押せば、ベータパッチが導入された状態で起動できます。 以後、Arma2Launcherから起動するだけで、簡単にdayzをプレイすることが可能になります。
https://w.atwiki.jp/commaou/pages/98.html
引き続き自称マネージャーと渋いミノタウロスがここまお機能チュートリアルをお送りいたします。 プロローグ 討伐戦概要 討伐戦予告 討伐戦準備期間 討伐戦 討伐戦終了 プロローグ ミノタウロス「ふ、フランベリー殿おおおおおおっ!!!」 フランベリー「hai!」 ミノタウロス「な・・・なんか出たでござる・・・」 フランベリー「お化けですか?」 ミノタウロス「と、とにかくくるでござる!」 フランベリー「あーれー」 フランベリー「・・・なるほど とうとう出ましたか・・・」 ミノタウロス「何がでござるかっ」 フランベリー「勇者です。」 ミノタウロス「なんと・・・ 強いのでござるか?」 フランベリー「まず一人では勝ち目がありません。」 ミノタウロス「うおおおお・・・拙者はここまでなのかあああっ・・・」 フランベリー「落ち着いてください。一人では勝ち目がありませんが、仲間がいれば・・・」 ミノタウロス「えっ」 討伐戦概要 フランベリー「このような予告がきた場合は討伐戦という特殊な戦闘が始まる合図です。」 ミノタウロス「討伐戦・・・でござるか」 フランベリー「討伐戦のみ、複数の仲間と連携して敵と戦うことができます。」 ミノタウロス「なんと・・・ ど、どうすれば参加できるでござるかっ!?」 フランベリー「落ち着いてくださいっ 今から説明します。 討伐戦の流れは以下の通りです。」 討伐戦予告 レス番号下2桁が85になると稀に討伐戦予告レスが自動で書き込まれます。 ↓ 討伐戦準備期間 予告レス後15レスの間はこの討伐戦に参加する魔物のエントリー期間です。 ↓ 討伐戦 レス番号下2桁が0になると討伐戦が始まります。1レスごとに3ターン経過し、10レス(合計30ターン)まで戦闘が行われます。 ↓ 討伐戦終了 敵が倒れるか仲間が全滅するか時間切れで終了です。 ミノタウロス「なるほど。今は討伐戦準備期間なのでござるな。」 フランベリー「そして、まだあせらなくても大丈夫ってことです。」 討伐戦予告レス フランベリー「では先ほどの予告レスを見ましょう。」 ミノタウロス「何か気になるところでも・・・ む、新米勇者の予感とあるでござるな。」 フランベリー「ということは現れるのは勇者ハジメですね。」 ミノタウロス「なるほど 予告レスから相手が予想できるのでござるね」 フランベリー「そうです。討伐戦で現れる敵もタイプが存在するので、この情報を元に作戦を立てるのが良いでしょう。」 ミノタウロス「しかし勇者は何タイプなのか・・・ ッ・・・ まさか!?」 フランベリー「お察しの通り。主に万能型です。」 ミノタウロス「そ、それではどうやって攻略すればよいのでござるか!?」 フランベリー「万能型は、言い方を変えればステータスに偏りがないので、ステータスの偏りのある敵よりは弱点による即死をそれほど気にしなくても大丈夫です。」 ミノタウロス「即死・・・」 討伐戦準備期間 フランベリー「討伐戦準備期間では、goコマンドとloginコマンドのみ使用できます。goコマンドで討伐戦に参加します。」 ミノタウロス「そのときにいつもどおり自分の行動も決定するのでござるね。」 フランベリー「はい。仲間とよく話し合って決めたほうが良いでしょう。」 ミノタウロス「そんなに重要なのでござるか?」 フランベリー「そうですね・・・。連携の話は後ほどしましょう。今回は私とミノタウロス様しかいらっしゃらな・・・」 ???「ん? あー・・・そこにいるのは」 フランベリー「はっ・・・ 死神姫様!」 ミノタウロス「死神姫・・・?」 死神姫「ほほーう・・・ あんたが男連れとはやるねぇ・・・」 フランベリー「えっ」 ミノタウロス「えっ」 死神姫「いやー!照れなくてもいいんだよ!はっはっはー」 フランベリー「し、紹介します・・・ こちら私の上司の死神姫様で・・・ こちらは地下調査隊のミノタウロス様です。」 死神姫「ミノタウロスね!よろしくよろしく! いやー神官様に探し物を頼まれて、見つかったから今戻ろうとしてたところなんだけど どうやら勇者が出たみたいだねー」 フランベリー「あ、あの・・・ 参加してくれm」 死神姫「あたい帰るね!」 フランベリー「ショボーン」 死神姫「・・・あっはっは 冗談だよ冗談!さぁとっととやっちまうよ!」 ミノタウロス「(うさんくさいでござる・・・)」 討伐戦 死神姫「たしかフランは防御型だったね ・・・あんたは攻撃型かい?」 ミノタウロス「いかにも」 死神姫「ちなみにあたいは魔法型だ というわけで作戦はこうしよう・・・」 ・・・ ミノタウロス「フランベリー殿」 フランベリー「な、なんですか? 死亡フラグは立ててませんよっ」 ミノタウロス「えっ」 フランベリー「なんでもないですっ」 ミノタウロス「討伐戦は通常の戦闘と他に違うところはあるのでござるか?」 フランベリー「あります。先ほどの表に書いたとおり、戦闘はレス番号下2桁が00になったとき始まります。1レス毎に3ターン経過し、制限時間は30ターンまでです。」 ミノタウロス「ふむ・・・ちなみにあの上司は信用していいのでござるか・・・?」 フランベリー「す、少し抜けてる部分もあると思いますが実力はありますよっ」 ミノタウロス「むむむ・・・ ッ! どうやら来たでござるな」 死神姫「いくよ!お前さん方!準備よろしく!」 フランベリー「り、了解ですっ」 ミノタウロス「御意ッ」 ハジメ「たおすぞーっ!」 死神姫「さぁあんたの相手はあたいだよ!」 ハジメ「強いぞーっ!」 フランベリー(これでヘイトは一度死神姫様に・・・ ってあれ?) ハジメ「うりゃーっ!!」 死神姫「なっ・・・追加攻撃も与えてヘイトは十分だったはず・・・」 ミノタウロス「おい!」 死神姫「大丈夫だ! いくよっ!」 ミノタウロス「なっ・・・ なんでござるかそのスキル!?」 死神姫「あたい専用っ♪ これでハジメのHPとあたいのHPが入れ替わって実質15ダメージ与えた! さぁ一気に詰めるよ!」 ミノタウロス(そんなむちゃくちゃなっ・・・ しかし・・・) フランベリー「っ・・・ ガードいきます!」 ミノタウロス「うおおおおおおおっ」 ミノタウロス(やるしかないッ!!!) 死神姫「いい攻撃だ!」 ハジメ「むーっ! 牛のくせに生意気だ!」 ミノタウロス(しまった・・・ヘイトがこっちにっ) フランベリー「やらせません!」 ミノタウロス「かたじけない!」 死神姫「いまだ!ぶつけてやりな!」 ミノタウロス「おう!」 うおおおおおおおおおおおおおおおおおっ ハジメ「にゃああああああああああああっ!!!!!」 討伐戦終了 ミノタウロス「ものすごい経験値・・・」 フランベリー「やりましたね!」 死神姫「ああ・・・ ハジメの最初の攻撃があたいに向いてたらもっとはやく片付いてただろうけどねぇ・・・ 失敗失敗! しかしまぁフランのプロボークも、ミノタウロスの追撃も見事だった!」 ミノタウロス「お、おう」テレテレ 死神姫「それじゃあたいは先に戻るよ!お二人とも仲良くなー!」 フランベリー「・・・ こ、このように討伐戦は経験値がものすごい量手に入ります・・・ レベルアップをしたいと思った場合、討伐戦にむけて準備するのが一番の近道です。」 ミノタウロス「そ、そうでござるか」 フランベリー「そして同時に討伐戦こそこの調査の主な目的、目標です。」 ミノタウロス「・・・で ござるな 拙者、がんばるでござるよ ・・・デュフフwwwww」(褒められて興奮している フランベリー「・・・?」
https://w.atwiki.jp/mitim/pages/22.html
注意書き この文章はMTSのチュートリアル Tutorial Meshing Objects in TS3 の意訳です。 ただし、書き出しの文章までは訳していません。 また、10/1現在の各ツールに合わせて記述を変更している箇所があります。 訳ミス等を見つけてしまったら、メールで連絡を。(文章を読んで頭が「?」で埋まったら、原文を参照してください) The Sims 3 のオブジェクト(メッシュ)のつくり方 必要なもの S3PE S3OC Object Tool by Wesh Milkshape 3D UV Mapper ※訳注 Object Toolは新URLに修正 これらプログラムは常に更新されている(Milkshape 3DとUV Mapperについてはその限りでもないが)、これら3ツールは最新のバージョンのものを使い、更新をチェックすること(少なくても私はそうしている)。 始める前に OK、注意書きをいくつか。これはとても基本的なチュートリアルだ。このチュートリアルに沿って作業すれば、メッシュの作り方のアウトラインがなんら問題なくメッシュを作成できる。 もしあなたがメッシュの作り方を知らないのなら、ここが何を言っているのかわからず途方に暮れるだろう。ここは中級-上級程度の実力が必要(各ステップは、あなたが当然知っているだろうという事には言及していない)だ。 上記に出したプログラムはすべてインストールしてあること。いくつかのサブプログラムも必要に応じて。 WesH’s Object toolにあるMilkshapeプラグインは必ず入れておくこと。.mcfgファイルのインポート/エクスポートが可能になる。 クローニングできないもの:地球儀とClutter-ゴチャゴチャ系(修飾)オブジェクトは、何とも言えないテクスチャを使っていて最適化されてしまっている。 そしてもう一つアドバイスするなら、最初に車のような難しいものを作ろうとしないことだ(そう考えることは絶対に間違っている)。イスかテーブルにしておくべきだ。 Step 1 クローニング S3OCを立ち上げ、"file new(clone)"をクリックする。目的のものがあったりモジュール式オブジェクトを作りたかったりするのなら、"Cloning 目的のカテゴリ"でもいい。 リストをロードしている間しばし待ち、複製したいアイテムを選択する。 ※ Clutter-ゴチャゴチャ系オブジェクトについては前述のとおり。 アイテムを選択したら、右ペインのさまざまな設定はなにも変えないこと。チェックボックスも記述文もそのまま。 "Clone or Fix..."ボタンを押して表示されるオプション画面で" Create missing string table "チェックボックスにチェックを入れ、"Unique name"にあるMODの名前を一意性があるような名前にする。(デフォルトで、"作成者名_オリジナルオブジェクト名"となる) "start"ボタンを押し、保存ダイアログで"保存(S)"をクリック、しばらく待つ。 終わったらS3OCは閉じていい。 ※訳注 S3OCのバージョンが上がり、GUI操作になったため、記述を書き直し。 赤文字部分の訳 もしオリジナルオブジェクトの構造からパーツを抜いたりする必要があるなら、リナンバリングする前にやること。 Step 2 ファイルの解凍 S3PEを立ち上げ、"file open"を選択、先ほどS3OCで保存したファイルを開く。 ウィンドウ下ペインにある"Sort"チェックボックスをチェックし、上右ペインの"Tag"項目名ボタンでタグ名順にソートする。 ※訳注 下ペインにある"Display Tags"チェックボックスもチェックすること。 色々なファイルがあるが、その中にMLODファイルが3本、MODLファイルが1本ある。それらの"Group"を見ると、0x000010001のようなナンバリングになっている。メインメッシュのMLODファイルのナンバーには 1 は含まれていない。0x00000000になっている。 その他2つのMLODファイルとMODLはオブジェクトの影をコントロールしている。 これらのファイルを適当なフォルダに"File Export"したら、S3PEは最小化しておく。 Step 3 Milkshapeの前準備 Object Toolを立ち上げる。 "Decompile"ボタンをクリック、S3PEでファイルをエクスポートしたフォルダを開き、ファイルをクリックして読み込む。メッセージ欄に No Errors と表示されれば、無事にファイルが解凍されている。 上記をS3PEで解凍した4ファイル(MODLが拡張子.modelファイルに、MLODが拡張子.lodファイルになっている)すべてに行う。 すると、フォルダ内に大量のファイルが現れる。その中に、MLODおよびMODLファイルに対応して一つずつ.mcfgファイルがあるはず。これがMilkshapeで使うメッシュデータのファイルだ。 ※ MLOD、MODLファイルを解凍する前に専用のフォルダを掘って、そこに各ファイルを置いて作業するのは、いい考えだ。様々なファイルの群れを見てあなたが混乱しなくて済む。 ※訳注 Object Toolのバージョンが上がり、GUI操作になったため、記述をほぼ全面書き直し。 Step 4 しばらくMilkshape作業 OK、Milkshapeを立ち上げて"file import Sims 3 Object Import by Wesley Howe"を選択。上記で解凍して得た.mcfgファイル(編集したいもの)を選んで"開く(O)"ボタンを押す。 作業すべきメインメッシュは、Groupsタブで group00 というグループ名のものだ(.mcfg共通)。さあ、メッシュを作ろう。(.mcfgファイルにエクスポートし直す前にオブジェクトのUVマッピングが必要になる。) 編集を終えたら(そしてUVマッピングも終えたら)、"file export Sims 3 Object Export by Wesley Howe"を選択する。保存ダイアログでは、ファイル名は変えずに保存すること! インポートしたものと本当に同じ名前かなんて強制はできないけれど。(※訳注 自分の目で確認してね、という意味?) 作業が終わったらMilkshapeを閉じて次に進む。 Step 5 インポートの用意 すべてのMODLファイルとMLODファイル分の編集を終えたら、S3PE作業に戻る準備をする必要がある。 Object Toolを立ち上げる。"Recompile"ボタンをクリック、フォルダを開き、.mcfgファイルをクリックして読み込む。メッセージ欄に No Errors と表示されれば、無事にMLOD(.lod)/MODL(.model)ファイルが再作成されている。 上記を編集した4つの.mcfgファイルすべてに行う。 ※訳注 Object Toolのバージョンが上がり、GUI操作になったため、記述をほぼ全面書き直し。 Step 6 S3PE作業 さあ、最小化していたS3PEを元に戻そう。 "file import"でMODL(.model)ファイルとMLOD(.lod)ファイルをパッケージにインポートし直す。リスト上の同じ名前のファイルが上書きされる。 ここで"file save"でセーブしよう。 Step 7 テクスチャとかあれこれ S3PEのリストをtagsでソートして、"_IMG"ファイルを見つける。関連する2ファイルを含むすべてをエクスポート(残念ながら、全部書き出して自分で見つけるしか手がない)する。(※訳注 拡張子は.dds) 必要な2ファイルは次の通り。 パーツマスク CASテーブルで見栄えをコントロールしている。見掛けは赤と緑の染みか、赤一色か、赤・青・緑になっている。 ※ 小さな赤い四角のファイルがあるが、これは違う。パーツマスクは大きな赤一色。 テクスチャ グレースケールで描かれたテクスチャがある。このファイルについてはここでは言及しない。メッシュとテクスチャの関係を知っている人が読んでいるはずだから。 求めるべき2つのファイルが見つかったら、テクスチャとそのパーツマスクを相応しいものに編集する。 パーツマスクの赤は最初のカラーチェンジエリア、緑は2番目のエリア、青は3番目、アルファチャンネルは4番目となっている。多くのオブジェクトは1個か2個しかエリアがない。 CASテーブル既存のパーツをメッシュに加えてはいけない。必ずクローンしたもののみ使用すること。 テクスチャはクローンしたものと同じようになる。けして画像サイズを変えてはいけないし、グレースケールにすること。 2つのファイルを編集したら、名前を変更しないでセーブする。 Step 8 またS3PE作業 さて、またS3PEに戻ってきた。"file import"で編集した_IMGファイルをインポートし直す。リスト上の同じ名前のものが上書きされる。 ここで"file save"でセーブしたら、S3PEは閉じる。 Step 9 "調整"段階 メッシュ作成もマッピング作業も全て、そして完璧に終えた。ふたたびS3OCを立ち上げよう。 "file open(fix)"を選択してS3PEで編集し終えたファイル(.package)を開く。 右ペイン"Overview"タグにある、"Price"(価格)、"Catalog Name"(商品名)、"Catalog Desc"(商品説明)を考えたものに編集できる。しかし、"Object Name"と"Object Desc"は編集してはいけない。 最後に、メッシュのサムネール画像を置き換える。でもまだ丁度いい画像なんて持っていないはずだし、後でもできる。 "Start"ボタンを押してゲーム内で一意になる名前を付けたら、"ok"ボタンを押してセーブしよう。インフォメーションダイアログが出て結果が ok だったら、"ok"ボタンを押して終わり。 ※訳注 これらの項目、一度"Clone or Fix..."ボタンを押して"Cancel"しないと編集可能にならない。なんで? また、"Copy English to all languages"にチェックを入れておき、表記はすべて英語表記した方が良い様子。 日本語対応は別途調査中。 Step 10 テスト 手元には完成した新しいメッシュ(オリジナルを置換せず、CASテーブルにも対応している)がある。(※ フェンスとかゴチャゴチャ系オブジェクトのように、いくつかのオブジェクトにはCASテーブルに対応していない)あとやるべき事は、.packageファイルをゲームに組み込むことだ。私的にはDelphy’s Install Helper Monkeyを使ってるけど、それぞれ自分のやり方で。 さあ、ゲームを立ち上げて輝ける新しいメッシュを確認してみよう!お見事! Step 11 問題が… すばらしい、どんな問題を抱えてようと、シムズを続けようよ!(驚異的なユーモアをどこかに入れたかったんだ) もし何か問題やトラブルを抱えてるなら忠告。それをここにポストしないで、限られたヘルプしかできないから。Sims3 Meshing Forumにポストしてね。 ありがとう。 このチュートリアルが熱心なメッシュ作成者みんなの助けになりますように。 行き詰ったときにはイヤになるよね。でも、今やあなたは知識もやるタイミングも得た! この場を借りて、メッシュの作成を教えてくれたLeesesterに感謝したい。おかげで私はあなたを教えられる。 そして私を助けてくれたIRCのMOD chatのみんなにも。 ※訳注 この章だけ訳がかなりあやしい。本筋じゃないので、とりあえずこれで。 DD
https://w.atwiki.jp/akasatanahama/pages/106.html
概要 MOD製作チュートリアル/TileEntityの追加で追加したTileEntityにGUI(Graphical User Interface)を実装する。 動作確認済バージョン:1.7.10-10.13.4.1558 ソースコード AluminiumMod.java package tutorial.aluminiummod; import cpw.mods.fml.common.Mod; import cpw.mods.fml.common.Mod.EventHandler; import cpw.mods.fml.common.Mod.Instance; import cpw.mods.fml.common.event.FMLPreInitializationEvent; import cpw.mods.fml.common.network.NetworkRegistry; import cpw.mods.fml.common.registry.GameRegistry; import net.minecraft.block.Block; @Mod(modid = AluminiumMod.MODID, name = AluminiumMod.MODNAME, version = AluminiumMod.VERSION) public class AluminiumMod { public static final String MODID = "AluminiumMod"; public static final String MODNAME = "Aluminium Mod"; public static final String VERSION = "1.0.0"; @Instance(MODID) public static AluminiumMod instance; public static Block chestAluminium; @EventHandler public void perInit(FMLPreInitializationEvent event) { chestAluminium = new BlockAluminiumChest() .setBlockName("chestAluminium") .setBlockTextureName("aluminiummod Aluminium_Chest"); GameRegistry.registerBlock(chestAluminium, "chestAluminium"); GameRegistry.registerTileEntity(TileEntityAluminiumChest.class, "TileEntityAluminiumChest"); NetworkRegistry.INSTANCE.registerGuiHandler(this.instance, new AluminiumModGuiHandler()); } } BlockAluminiumChest.java package tutorial.aluminiummod; import java.util.Random; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class BlockAluminiumChest extends Block implements ITileEntityProvider { private Random random = new Random(); public BlockAluminiumChest() { super(Material.rock); this.setCreativeTab(CreativeTabs.tabDecorations); this.setHardness(5.0F); this.setResistance(1.0F); this.setStepSound(soundTypeMetal); isBlockContainer = true; } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityAluminiumChest(); } @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { // GUIを開く。 player.openGui(AluminiumMod.instance, 1, world, x, y, z); return true; } @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { // TileEntityの内部にあるアイテムをドロップさせる。 TileEntityAluminiumChest tileentity = (TileEntityAluminiumChest) world.getTileEntity(x, y, z); if (tileentity != null) { for (int i = 0; i tileentity.getSizeInventory(); i++) { ItemStack itemStack = tileentity.getStackInSlot(i); if (itemStack != null) { float f = random.nextFloat() * 0.6F + 0.1F; float f1 = random.nextFloat() * 0.6F + 0.1F; float f2 = random.nextFloat() * 0.6F + 0.1F; while (itemStack.stackSize 0) { int j = random.nextInt(21) + 10; if (j itemStack.stackSize) { j = itemStack.stackSize; } itemStack.stackSize -= j; EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2, new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage())); if (itemStack.hasTagCompound()) { entityItem.getEntityItem() .setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy())); } float f3 = 0.025F; entityItem.motionX = (float) random.nextGaussian() * f3; entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F; entityItem.motionZ = (float) random.nextGaussian() * f3; world.spawnEntityInWorld(entityItem); } } } world.func_147453_f(x, y, z, block); } super.breakBlock(world, x, y, z, block, meta); } } TileEntityAluminiumChest.java package tutorial.aluminiummod; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; public class TileEntityAluminiumChest extends TileEntity implements IInventory { protected ItemStack[] itemStacks = new ItemStack[54]; @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); NBTTagList nbttaglist = new NBTTagList(); for (int i = 0; i itemStacks.length; i++) { if (itemStacks[i] == null) continue; NBTTagCompound nbt1 = new NBTTagCompound(); nbt1.setByte("Slot", (byte) i); itemStacks[i].writeToNBT(nbt1); nbttaglist.appendTag(nbt1); } nbt.setTag("Items", nbttaglist); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTTagList nbttaglist = nbt.getTagList("Items", 10); itemStacks = new ItemStack[54]; for (int i = 0; i nbttaglist.tagCount(); i++) { NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i); byte b0 = nbt1.getByte("Slot"); if (0 = b0 b0 itemStacks.length) { itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1); } } } @Override public int getSizeInventory() { return 54; } @Override public ItemStack getStackInSlot(int slot) { return itemStacks[slot]; } @Override public ItemStack decrStackSize(int slot, int amount) { if (itemStacks[slot] == null) return null; ItemStack itemstack; if (itemStacks[slot].stackSize = amount) { itemstack = itemStacks[slot]; itemStacks[slot] = null; return itemstack; } itemstack = itemStacks[slot].splitStack(amount); if (itemStacks[slot].stackSize 1) { itemStacks[slot] = null; } return itemstack; } @Override public ItemStack getStackInSlotOnClosing(int slot) { return null; } @Override public void setInventorySlotContents(int slot, ItemStack itemStack) { itemStacks[slot] = itemStack; if (itemStack != null itemStack.stackSize this.getInventoryStackLimit()) { itemStack.stackSize = this.getInventoryStackLimit(); } } @Override public boolean hasCustomInventoryName() { return false; } @Override public String getInventoryName() { return "container.AluminiumMod.AluminiumChest"; } @Override public int getInventoryStackLimit() { return 64; } @Override public boolean isUseableByPlayer(EntityPlayer player) { return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) = 64.0D; } @Override public void openInventory() {} @Override public void closeInventory() {} @Override public boolean isItemValidForSlot(int slot, ItemStack itemStack) { return true; } } AluminiumModGuiHandler.java package tutorial.aluminiummod; import cpw.mods.fml.common.network.IGuiHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.tileentity.TileEntity; import net.minecraft.world.World; public class AluminiumModGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntityAluminiumChest) { return new ContainerAluminiumChest(player, (TileEntityAluminiumChest) tileentity); } return null; } @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntityAluminiumChest) { return new GuiAluminiumChest(player, (TileEntityAluminiumChest) tileentity); } return null; } } ContainerAluminiumChest.java package tutorial.aluminiummod; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; public class ContainerAluminiumChest extends Container { private TileEntityAluminiumChest tileEntity; /** アルミニウムチェストのインベントリの第一スロットの番号 */ private static final int index0 = 0; /** プレイヤーのインベントリの第一スロットの番号 */ private static final int index1 = 54; /** クイックスロットの第一スロットの番号 */ private static final int index2 = 81; /** このコンテナの全体のスロット数 */ private static final int index3 = 90; public ContainerAluminiumChest(EntityPlayer player, TileEntityAluminiumChest tileEntity) { // スロットを設定する。 this.tileEntity = tileEntity; for (int iy = 0; iy 6; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(tileEntity, ix + (iy * 9), 8 + (ix * 18), 18 + (iy * 18))); } } for (int iy = 0; iy 3; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix + (iy * 9) + 9, 8 + (ix * 18), 140 + (iy * 18))); } } for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix, 8 + (ix * 18), 198)); } } @Override public boolean canInteractWith(EntityPlayer player) { return tileEntity.isUseableByPlayer(player); } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) { ItemStack itemStack = null; Slot slot = (Slot) inventorySlots.get(slotNumber); if (slot != null slot.getHasStack()) { ItemStack itemStack1 = slot.getStack(); itemStack = itemStack1.copy(); if (index0 = slotNumber slotNumber index1) { // アルミニウムチェストのインベントリならプレイヤーのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index1, index3, true)) { return null; } } else { // プレイヤーのインベントリならアルミニウムチェストのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index0, index1, false)) { return null; } } if (itemStack1.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } if (itemStack1.stackSize == itemStack.stackSize) { return null; } slot.onPickupFromSlot(player, itemStack1); } return itemStack; } } GuiAluminiumChest.java package tutorial.aluminiummod; import org.lwjgl.opengl.GL11; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; public class GuiAluminiumChest extends GuiContainer { private TileEntityAluminiumChest tileEntity; // GUIのテクスチャの場所を指定する。今回はバニラのラージチェストと同じものを使う。 private static final ResourceLocation GUITEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); public GuiAluminiumChest(EntityPlayer player, TileEntityAluminiumChest tileEnttiy) { super(new ContainerAluminiumChest(player, tileEnttiy)); this.tileEntity = tileEnttiy; ySize = 222; } @Override protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { fontRendererObj.drawString(StatCollector.translateToLocal(tileEntity.getInventoryName()), 8, 6, 4210752); fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752); } @Override protected void drawGuiContainerBackgroundLayer(float tick, int mouseX, int mouseY) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); mc.getTextureManager().bindTexture(GUITEXTURE); int k = (width - xSize) / 2; int l = (height - ySize) / 2; this.drawTexturedModalRect(k, l, 0, 0, xSize, ySize); } } 解説 Instance String modid コアクラスのインスタンスにつけるアノテーション。 登録やインスタンスの生成・代入はForge側がやってくれるので何もしなくてよい。 NetworkRegistry GUIやパケットなどを管理するenum。 void registerGuiHandler(Object mod, IGuiHandler handler) MODのコアクラスのインスタンスと、それに対応したGuiHandlerを登録する処理。 EntityPlayer プレイヤーのEntity継承クラス。 void openGui(Object mod, int modGuiId, World world, int x, int y, int z) 第一引数はコアクラスのインスタンス、第二引数はMOD内でのGUIのID。 プレイヤーにGUIを開かせる。 IGuiHandler GuiHandlerのためのインターフェース。 Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) サーバー側で呼ばれる。 基本的にはIDに対応したContainerを返す。 Worldのインスタンスと座標も引数に含まれているので、TileEntityを取得して判別してもよい。 Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) クライアント側で呼ばれる。 基本的にはIDに対応したGuiを返す。 Container Slot addSlotToContainer(Slot slot) 新たなSlotをコンテナに登録する処理。 boolean canInteractWith(EntityPlayer player) プレイヤーがコンテナを使えるかどうかの判定。 ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) スロットがShift+クリックされた時の処理。 クリックされたスロットの中身を移動する。 boolean mergeItemStack(ItemStack itemStack, int beginIndex, int endIndex, boolean doReverse) 引数のItemStackを指定された範囲内の空のスロットに移動する。 範囲は、beginIndexを含み、endIndexは含まない。 doReverseがtrueの場合は、検索方向がend→beginになる。 GuiContainer コンテナを持つGUIのクラス。 クライアントのみで使用される。 public GuiContainer(Container container) 引数は対応するコンテナ。 void drawGuiContainerForegroundLayer(int mouseX, int mouseY) Guiの前面レイヤーを描画する処理。 文字の描画などをする。 void drawGuiContainerBackgroundLayer(float tick, int mouseX, int mouseY) Guiの背景レイヤーを描画する処理。 Guiのテクスチャの描画などをする。 ResourceLocation リソースの場所を保持するクラス。 public ResourceLocation(String path) コンストラクタ。 引数でリソースの場所を指定する。 "modid textures/..."というように、すべて小文字にしたMODIDと、textures以下のファイルのパスを指定する。 例えば、assets/aluminiummod/textures/gui/gui.pngだとすると、private static final ResourceLocation GUITEXTURE = new ResourceLocation("aluminiummod textures/gui/gui.png");と記述する。 なお、GUIのテクスチャは画像ファイルを正方形にしないと縦横比がおかしくなる可能性があるので、カンバスサイズを256x256や512x512などにしておいて、余白を透明で残しておくと良い。 使用例 オファレンプレゼントボックスを追加している部分。 +オファレンMOD OfalenModCore.java package nahama.ofalenmod; /*略*/ /** * @author Akasata Nahama */ @Mod(modid = OfalenModCore.MODID, name = OfalenModCore.MODNAME, version = OfalenModCore.VERSION) public class OfalenModCore { public static final String MODID = "OfalenMod"; public static final String MODNAME = "Ofalen Mod"; public static final String MCVERSION = "1.7.10"; public static final String OMVERSION = "1.1.0"; public static final String VERSION = "[" + MCVERSION + "]" + OMVERSION; /** coreクラスのインスタンス */ @Instance(MODID) public static OfalenModCore instance; /*略*/ /** 初期化前処理。 */ @EventHandler public void preInit(FMLPreInitializationEvent event) { /*略*/ OfalenModBlockCore.registerBlock(); // 機械類のGUIを登録する。 NetworkRegistry.INSTANCE.registerGuiHandler(this.instance, new OfalenModGuiHandler()); /*略*/ } /*略*/ } OfalenModBlockCore.java package nahama.ofalenmod.core; /*略*/ public class OfalenModBlockCore { /*略*/ public static Block boxPresentOfalen; /** ブロックを登録する処理。 */ public static void registerBlock() { /*略*/ boxPresentOfalen = new BlockPresentBox() .setBlockName("boxPresentOfalen") .setBlockTextureName("ofalenmod present_box"); GameRegistry.registerBlock(boxPresentOfalen, "boxPresentOfalen"); GameRegistry.registerTileEntity(TileEntityPresentBox.class, "TileEntityOfalenPresentBox"); } } BlockPresentBox.java package nahama.ofalenmod.block; import java.util.Random; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import nahama.ofalenmod.OfalenModCore; import nahama.ofalenmod.handler.OfalenModAnniversaryHandler; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.block.Block; import net.minecraft.block.ITileEntityProvider; import net.minecraft.block.material.Material; import net.minecraft.client.renderer.texture.IIconRegister; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.IIcon; import net.minecraft.world.World; public class BlockPresentBox extends Block implements ITileEntityProvider { private Random random = new Random(); /** 0 下,1 上,2 横,3 クリスマス下,4;クリスマス上,5 クリスマス横 */ private IIcon[] iicon = new IIcon[6]; public BlockPresentBox() { super(Material.sponge); this.setCreativeTab(OfalenModCore.tabOfalen); this.setHardness(1.0F); this.setResistance(1.0F); this.setStepSound(Block.soundTypeCloth); } @Override public TileEntity createNewTileEntity(World world, int meta) { return new TileEntityPresentBox(); } /** プレイヤーに右クリックされたときの処理。 */ @Override public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int side, float hitX, float hitY, float hitZ) { // GUIを開く player.openGui(OfalenModCore.instance, 1, world, x, y, z); return true; } /** ブロックが破壊された時の処理。 */ @Override public void breakBlock(World world, int x, int y, int z, Block block, int meta) { // TileEntityの内部にあるアイテムをドロップさせる。 TileEntityPresentBox tileentity = (TileEntityPresentBox) world.getTileEntity(x, y, z); if (tileentity != null) { for (int i = 0; i tileentity.getSizeInventory(); i++) { ItemStack itemStack = tileentity.getStackInSlot(i); if (itemStack != null) { float f = random.nextFloat() * 0.6F + 0.1F; float f1 = random.nextFloat() * 0.6F + 0.1F; float f2 = random.nextFloat() * 0.6F + 0.1F; while (itemStack.stackSize 0) { int j = random.nextInt(21) + 10; if (j itemStack.stackSize) { j = itemStack.stackSize; } itemStack.stackSize -= j; EntityItem entityItem = new EntityItem(world, x + f, y + f1, z + f2, new ItemStack(itemStack.getItem(), j, itemStack.getItemDamage())); if (itemStack.hasTagCompound()) { entityItem.getEntityItem().setTagCompound(((NBTTagCompound) itemStack.getTagCompound().copy())); } float f3 = 0.025F; entityItem.motionX = (float) random.nextGaussian() * f3; entityItem.motionY = (float) random.nextGaussian() * f3 + 0.1F; entityItem.motionZ = (float) random.nextGaussian() * f3; world.spawnEntityInWorld(entityItem); } } } world.func_147453_f(x, y, z, block); } super.breakBlock(world, x, y, z, block, meta); } /** ブロックのアイコンを登録する処理。 */ @Override @SideOnly(Side.CLIENT) public void registerBlockIcons(IIconRegister register) { for (int i = 0; i 6; i++) { iicon[i] = register.registerIcon(this.getTextureName() + "-" + i); } } /** ブロックのアイコンを返す。 */ @Override @SideOnly(Side.CLIENT) public IIcon getIcon(int side, int meta) { int i = 2; if (side == 0) i = 0; if (side == 1) i = 1; if (OfalenModAnniversaryHandler.isChristmas) i += 3; return iicon[i]; } } TileEntityPresentBox.java package nahama.ofalenmod.tileentity; import nahama.ofalenmod.handler.OfalenModAnniversaryHandler; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.tileentity.TileEntity; public class TileEntityPresentBox extends TileEntity implements IInventory { protected ItemStack[] itemStacks = new ItemStack[54]; protected String owner; /** プレイヤーがインベントリを開けた時の処理。 */ public void openInventory(EntityPlayer player) { if (owner != null || worldObj.isRemote) return; // オーナーに設定し、中身を上書きする。 owner = player.getCommandSenderName(); ItemStack[] presents = OfalenModAnniversaryHandler.getPresents(player); if (presents == null) return; itemStacks = presents; } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); NBTTagList nbttaglist = new NBTTagList(); for (int i = 0; i itemStacks.length; i++) { if (itemStacks[i] == null) continue; NBTTagCompound nbt1 = new NBTTagCompound(); nbt1.setByte("Slot", (byte) i); itemStacks[i].writeToNBT(nbt1); nbttaglist.appendTag(nbt1); } nbt.setTag("Items", nbttaglist); nbt.setString("Owner", owner); } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); NBTTagList nbttaglist = nbt.getTagList("Items", 10); itemStacks = new ItemStack[54]; for (int i = 0; i nbttaglist.tagCount(); i++) { NBTTagCompound nbt1 = nbttaglist.getCompoundTagAt(i); byte b0 = nbt1.getByte("Slot"); if (0 = b0 b0 itemStacks.length) { itemStacks[b0] = ItemStack.loadItemStackFromNBT(nbt1); } } owner = nbt.getString("Owner"); } /** インベントリのスロット数を返す。 */ @Override public int getSizeInventory() { return 54; } /** スロットのアイテムを返す。 */ @Override public ItemStack getStackInSlot(int slot) { return itemStacks[slot]; } /** スロットのスタック数を減らす。 */ @Override public ItemStack decrStackSize(int slot, int amount) { if (itemStacks[slot] == null) return null; ItemStack itemstack; if (itemStacks[slot].stackSize = amount) { itemstack = itemStacks[slot]; itemStacks[slot] = null; return itemstack; } itemstack = itemStacks[slot].splitStack(amount); if (itemStacks[slot].stackSize 1) { itemStacks[slot] = null; } return itemstack; } @Override public ItemStack getStackInSlotOnClosing(int slot) { return null; } /** スロットの中身を設定する。 */ @Override public void setInventorySlotContents(int slot, ItemStack itemStack) { itemStacks[slot] = itemStack; if (itemStack != null itemStack.stackSize this.getInventoryStackLimit()) { itemStack.stackSize = this.getInventoryStackLimit(); } } /** 金床で設定された名前を持つかどうか。 */ @Override public boolean hasCustomInventoryName() { return false; } /** インベントリの名前を返す。 */ @Override public String getInventoryName() { return "container.OfalenMod.PresentBox"; } /** このインベントリの最大スタック数を返す。 */ @Override public int getInventoryStackLimit() { return 64; } /** プレイヤーが使用できるかどうか。 */ @Override public boolean isUseableByPlayer(EntityPlayer player) { if (owner != null !player.getCommandSenderName().equals(owner)) return false; return worldObj.getTileEntity(xCoord, yCoord, zCoord) != this ? false player.getDistanceSq(xCoord + 0.5D, yCoord + 0.5D, zCoord + 0.5D) = 64.0D; } @Override public void openInventory() {} @Override public void closeInventory() {} /** スロットにアクセスできるかどうか。 */ @Override public boolean isItemValidForSlot(int slot, ItemStack itemStack) { return false; } } OfalenModGuiHandler.java package nahama.ofalenmod.handler; /*略*/ public class OfalenModGuiHandler implements IGuiHandler { @Override public Object getServerGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (id == 2) return new ContainerItemShield(player); if (id == 3) return new ContainerItemTeleporter(player); if (id == 4) return new ContainerItemFloater(player); if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntitySmeltingMachine) { return new ContainerSmeltingMachine(player, (TileEntitySmeltingMachine) tileentity); } if (tileentity instanceof TileEntityRepairMachine) { return new ContainerRepairMachine(player, (TileEntityRepairMachine) tileentity); } if (tileentity instanceof TileEntityConversionMachine) { return new ContainerConversionMachine(player, (TileEntityConversionMachine) tileentity); } if (tileentity instanceof TileEntityTeleportMarker) { return new ContainerTeleportMarker(player, (TileEntityTeleportMarker) tileentity); } if (tileentity instanceof TileEntityPresentBox) { return new ContainerPresentBox(player, (TileEntityPresentBox) tileentity); } return null; } @Override public Object getClientGuiElement(int id, EntityPlayer player, World world, int x, int y, int z) { if (id == 2) return new GuiItemShield(player); if (id == 3) return new GuiItemTeleporter(player); if (id == 4) return new GuiItemFloater(player); if (!world.blockExists(x, y, z)) return null; TileEntity tileentity = world.getTileEntity(x, y, z); if (tileentity instanceof TileEntitySmeltingMachine) { return new GuiSmeltingMachine(player, (TileEntitySmeltingMachine) tileentity); } if (tileentity instanceof TileEntityRepairMachine) { return new GuiRepairMachine(player, (TileEntityRepairMachine) tileentity); } if (tileentity instanceof TileEntityConversionMachine) { return new GuiConversionMachine(player, (TileEntityConversionMachine) tileentity); } if (tileentity instanceof TileEntityTeleportMarker) { return new GuiTeleportMarker(player, (TileEntityTeleportMarker) tileentity); } if (tileentity instanceof TileEntityPresentBox) { return new GuiPresentBox(player, (TileEntityPresentBox) tileentity); } return null; } } ContainerPresentBox.java package nahama.ofalenmod.inventory; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; public class ContainerPresentBox extends Container { private TileEntityPresentBox tileEntity; /** プレゼントボックスのインベントリの第一スロットの番号 */ private static final int index0 = 0; /** プレイヤーのインベントリの第一スロットの番号 */ private static final int index1 = 54; /** クイックスロットの第一スロットの番号 */ private static final int index2 = 81; /** このコンテナの全体のスロット数 */ private static final int index3 = 90; public ContainerPresentBox(EntityPlayer player, TileEntityPresentBox tileEntity) { this.tileEntity = tileEntity; tileEntity.openInventory(player); for (int iy = 0; iy 6; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(tileEntity, ix + (iy * 9), 8 + (ix * 18), 18 + (iy * 18))); } } for (int iy = 0; iy 3; iy++) { for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix + (iy * 9) + 9, 8 + (ix * 18), 140 + (iy * 18))); } } for (int ix = 0; ix 9; ix++) { this.addSlotToContainer(new Slot(player.inventory, ix, 8 + (ix * 18), 198)); } } @Override public boolean canInteractWith(EntityPlayer player) { return tileEntity.isUseableByPlayer(player); } @Override public ItemStack transferStackInSlot(EntityPlayer player, int slotNumber) { ItemStack itemStack = null; Slot slot = (Slot) inventorySlots.get(slotNumber); if (slot != null slot.getHasStack()) { ItemStack itemStack1 = slot.getStack(); itemStack = itemStack1.copy(); if (index0 = slotNumber slotNumber index1) { // プレゼントボックスのインベントリならプレイヤーのインベントリに移動。 if (!this.mergeItemStack(itemStack1, index1, index3, true)) { return null; } } else { if (index1 = slotNumber slotNumber index2) { // プレイヤーのインベントリならクイックスロットに移動。 if (!this.mergeItemStack(itemStack1, index2, index3, false)) { return null; } } else if (index2 = slotNumber slotNumber index3 !this.mergeItemStack(itemStack1, index1, index2, false)) { // クイックスロットからプレイヤーのインベントリに移動できなかったら終了。 return null; } } if (itemStack1.stackSize == 0) { slot.putStack((ItemStack) null); } else { slot.onSlotChanged(); } if (itemStack1.stackSize == itemStack.stackSize) { return null; } slot.onPickupFromSlot(player, itemStack1); } return itemStack; } } GuiPresentBox.java package nahama.ofalenmod.gui; import org.lwjgl.opengl.GL11; import nahama.ofalenmod.inventory.ContainerPresentBox; import nahama.ofalenmod.tileentity.TileEntityPresentBox; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.ResourceLocation; import net.minecraft.util.StatCollector; public class GuiPresentBox extends GuiContainer { private TileEntityPresentBox tileEntity; private static final ResourceLocation GUITEXTURE = new ResourceLocation("textures/gui/container/generic_54.png"); public GuiPresentBox(EntityPlayer player, TileEntityPresentBox tileEnttiy) { super(new ContainerPresentBox(player, tileEnttiy)); this.tileEntity = tileEnttiy; ySize = 222; } @Override protected void drawGuiContainerForegroundLayer(int par1, int par2) { fontRendererObj.drawString(StatCollector.translateToLocal(tileEntity.getInventoryName()), 8, 6, 4210752); fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), 8, ySize - 96 + 2, 4210752); } @Override protected void drawGuiContainerBackgroundLayer(float par1, int par2, int par3) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); mc.getTextureManager().bindTexture(GUITEXTURE); int k = (width - xSize) / 2; int l = (height - ySize) / 2; this.drawTexturedModalRect(k, l, 0, 0, xSize, ySize); } } コメント この項目に関する質問などをどうぞ。 GUIのテクスチャをオリジナルのものにする場合どう記述すれば、よいのでしょうか? - 新人もっだー 2015-12-20 12 20 13 解説/public ResourceLocation(String path)に追記しましたのでご確認ください。自分で指定したパスにバニラのラージチェストのテクスチャを改変したものを保存すればできます。 - Tom Kate 2015-12-21 16 52 24 コピペでもコンストラクター ContainerAluminiumChest(EntityPlayer, TileEntityChest) は未定義ですとなります。 - 新人もっだー 2015-12-26 11 26 55 それは、Eclipse上でコンパイルエラーの検出がされたということでしょうか?どの行でのエラーかを教えていただけないでしょうか。 - 赤砂蛇凪浜 2015-12-26 13 48 01 ContainerAluminiumChestのreturn new ContainerChest(player, (TileEntityChest) tileentity);no - 新人もっだー 2015-12-28 08 51 55 の行です - 新人もっだー 2015-12-28 08 52 37 このチュートリアルの中に該当する行がありません。一度コピー ペーストしなおしてみてください。 - 赤砂蛇凪浜 2015-12-28 09 36 26 import cpw.mods.fml.common.Mod.Instance;が書き込んでから保存するとなぜかそれだけ消えてしまうのですが、なんで何でしょうか? - san 2016-09-11 08 20 49 IDE(Eclipse)のimport文自動編集が消しているのだと思われます。@Instanceの部分にエラーが出ていなければ特に問題はないと思います。 - 赤砂蛇凪浜 2016-09-16 07 35 27 醸造台やエンチャント台、装備スロットのように、スロット内に一部のアイテムのみ入れられるようにするにはどうすれば良いのでしょうか? - 名無しさん 2016-12-02 01 33 32 addSlotToContainerでSlotを継承した自作のクラスを渡せばよいです。その際、isItemValidをオーバーライドすれば入れられるアイテムを、canTakeStackをオーバーライドすれば取り出せるアイテムを制御できます。分かりにくかったらすみません。後ほど本文への掲載も検討します。 - 赤砂蛇凪浜 2016-12-04 10 50 12 GUIに文字を入れて翻訳するのはどうやるんですか - HIROMARU (2021-01-09 11 38 30) 名前
https://w.atwiki.jp/arma2/pages/19.html
制作入門 http //www5b.biglobe.ne.jp/~u-hobby/game/arma/edit/index.html 質問等はこちらで http //ofpec.ath.cx/uploader/c-board.cgi